Add TAL-Reverb-II plugin to test
[juce-lv2.git] / juce / source / extras / the jucer / src / utility / jucer_UtilityFunctions.cpp
blob65df74d814453f060fd89ce3fccba9c1de8af1cf
1 /*
2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-11 by Raw Material Software Ltd.
7 ------------------------------------------------------------------------------
9 JUCE can be redistributed and/or modified under the terms of the GNU General
10 Public License (Version 2), as published by the Free Software Foundation.
11 A copy of the license is included in the JUCE distribution, or can be found
12 online at www.gnu.org/licenses.
14 JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 ------------------------------------------------------------------------------
20 To release a closed-source product which uses JUCE, commercial licenses are
21 available: visit www.rawmaterialsoftware.com/juce for more information.
23 ==============================================================================
26 #include "../jucer_Headers.h"
27 #include "../model/jucer_JucerDocument.h"
30 //==============================================================================
31 const String replaceCEscapeChars (const String& s)
33 const int len = s.length();
35 String r;
36 r.preallocateBytes (4 * len + 4);
37 bool lastWasHexEscapeCode = false;
39 for (int i = 0; i < len; ++i)
41 const juce_wchar c = s[i];
43 switch (c)
45 case '\t':
46 r << "\\t";
47 lastWasHexEscapeCode = false;
48 break;
49 case '\r':
50 r << "\\r";
51 lastWasHexEscapeCode = false;
52 break;
53 case '\n':
54 r << "\\n";
55 lastWasHexEscapeCode = false;
56 break;
57 case '\\':
58 r << "\\\\";
59 lastWasHexEscapeCode = false;
60 break;
61 case '\'':
62 r << "\\\'";
63 lastWasHexEscapeCode = false;
64 break;
65 case '\"':
66 r << "\\\"";
67 lastWasHexEscapeCode = false;
68 break;
70 default:
71 if (c < 128 &&
72 ! (lastWasHexEscapeCode
73 && String ("0123456789abcdefABCDEF").containsChar (c))) // (have to avoid following a hex escape sequence with a valid hex digit)
75 r << c;
76 lastWasHexEscapeCode = false;
78 else
80 lastWasHexEscapeCode = true;
81 r << "\\x" << String::toHexString ((int) c);
84 break;
88 return r;
91 const String quotedString (const String& s)
93 if (s.isEmpty())
94 return "String::empty";
96 const int embeddedIndex = s.indexOfIgnoreCase ("%%");
98 if (embeddedIndex >= 0)
100 String s1 (s.substring (0, embeddedIndex));
101 String s2 (s.substring (embeddedIndex + 2));
102 String code;
104 const int closeIndex = s2.indexOf ("%%");
106 if (closeIndex > 0)
108 code = s2.substring (0, closeIndex).trim();
109 s2 = s2.substring (closeIndex + 2);
112 if (code.isNotEmpty())
114 String result;
116 if (s1.isNotEmpty())
117 result << quotedString (s1) << " + ";
119 result << code;
121 if (s2.isNotEmpty())
122 result << " + " << quotedString (s2);
124 return result;
128 return "L\"" + replaceCEscapeChars (s) + "\"";
131 const String replaceStringTranslations (String s, JucerDocument* document)
133 s = s.replace ("%%getName()%%", document->getComponentName());
134 s = s.replace ("%%getButtonText()%%", document->getComponentName());
136 return s;
139 const String castToFloat (const String& expression)
141 if (expression.containsOnly ("0123456789.f"))
143 String s (expression.getFloatValue());
145 if (s.containsChar ('.'))
146 return s + "f";
148 return s + ".0f";
151 return "(float) (" + expression + ")";
154 const String indentCode (const String& code, const int numSpaces)
156 if (numSpaces == 0)
157 return code;
159 const String space (String::repeatedString (" ", numSpaces));
161 StringArray lines;
162 lines.addLines (code);
164 for (int i = 1; i < lines.size(); ++i)
166 String s (lines[i].trimEnd());
167 if (s.isNotEmpty())
168 s = space + s;
170 lines.set (i, s);
173 return lines.joinIntoString ("\n");
176 //==============================================================================
177 const String makeValidCppIdentifier (String s,
178 const bool capitalise,
179 const bool removeColons,
180 const bool allowTemplates)
182 if (removeColons)
183 s = s.replaceCharacters (".,;:/@", "______");
184 else
185 s = s.replaceCharacters (".,;/@", "_____");
187 int i;
188 for (i = s.length(); --i > 0;)
189 if (CharacterFunctions::isLetter (s[i])
190 && CharacterFunctions::isLetter (s[i - 1])
191 && CharacterFunctions::isUpperCase (s[i])
192 && ! CharacterFunctions::isUpperCase (s[i - 1]))
193 s = s.substring (0, i) + " " + s.substring (i);
195 String allowedChars ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_ 0123456789");
196 if (allowTemplates)
197 allowedChars += "<>";
199 if (! removeColons)
200 allowedChars += ":";
202 StringArray words;
203 words.addTokens (s.retainCharacters (allowedChars), false);
204 words.trim();
206 String n (words[0]);
208 if (capitalise)
209 n = n.toLowerCase();
211 for (i = 1; i < words.size(); ++i)
213 if (capitalise && words[i].length() > 1)
214 n << words[i].substring (0, 1).toUpperCase()
215 << words[i].substring (1).toLowerCase();
216 else
217 n << words[i];
220 if (CharacterFunctions::isDigit (n[0]))
221 n = "_" + n;
223 // make sure it's not a reserved c++ keyword..
224 static const char* const reservedWords[] =
226 "auto", "const", "double", "float", "int", "short", "struct",
227 "return", "static", "union", "while", "asm", "dynamic_cast",
228 "unsigned", "break", "continue", "else", "for", "long", "signed",
229 "switch", "void", "case", "default", "enum", "goto", "register",
230 "sizeof", "typedef", "volatile", "char", "do", "extern", "if",
231 "namespace", "reinterpret_cast", "try", "bool", "explicit", "new",
232 "static_cast", "typeid", "catch", "false", "operator", "template",
233 "typename", "class", "friend", "private", "this", "using", "const_cast",
234 "inline", "public", "throw", "virtual", "delete", "mutable", "protected",
235 "true", "wchar_t", "and", "bitand", "compl", "not_eq", "or_eq",
236 "xor_eq", "and_eq", "bitor", "not", "or", "xor", "cin", "endl",
237 "INT_MIN", "iomanip", "main", "npos", "std", "cout", "include",
238 "INT_MAX", "iostream", "MAX_RAND", "NULL", "string"
241 for (i = 0; i < numElementsInArray (reservedWords); ++i)
242 if (n == reservedWords[i])
243 n << '_';
245 return n;
248 //==============================================================================
249 int indexOfLineStartingWith (const StringArray& lines, const String& text, int startIndex)
251 startIndex = jmax (0, startIndex);
253 while (startIndex < lines.size())
255 if (lines[startIndex].trimStart().startsWithIgnoreCase (text))
256 return startIndex;
258 ++startIndex;
261 return -1;
264 //==============================================================================
265 const String valueToFloat (const double v)
267 String s ((double) (float) v, 4);
269 if (s.containsChar ('.'))
270 s << 'f';
271 else
272 s << ".0f";
274 return s;
277 const String boolToString (const bool b)
279 return b ? "true" : "false";
282 //==============================================================================
283 const String colourToHex (const Colour& col)
285 return String::toHexString ((int) col.getARGB());
288 //==============================================================================
289 const String colourToCode (const Colour& col)
291 #define COL(col) Colours::col,
293 const Colour colours[] =
295 #include "jucer_Colours.h"
296 Colours::transparentBlack
299 #undef COL
300 #define COL(col) #col,
301 static const char* colourNames[] =
303 #include "jucer_Colours.h"
306 #undef COL
308 for (int i = 0; i < numElementsInArray (colourNames) - 1; ++i)
309 if (col == colours[i])
310 return "Colours::" + String (colourNames[i]);
312 return "Colour (0x" + colourToHex (col) + ")";
315 void setColourXml (XmlElement& xml, const char* const attName, const Colour& colour)
317 xml.setAttribute (attName, colourToHex (colour));
320 const Colour getColourXml (const XmlElement& xml, const char* const attName, const Colour& defaultColour)
322 return Colour (xml.getStringAttribute (attName, colourToHex (defaultColour)).getHexValue32());
325 //==============================================================================
326 const String positionToString (const RelativePositionedRectangle& pos)
328 StringArray toks;
329 toks.addTokens (pos.rect.toString(), false);
331 return toks[0] + " " + toks[1];
334 void positionToXY (const RelativePositionedRectangle& position,
335 double& x, double& y,
336 const Rectangle<int>& parentArea,
337 const ComponentLayout* layout)
339 double w, h;
340 position.getRectangleDouble (x, y, w, h, parentArea, layout);
343 void positionToCode (const RelativePositionedRectangle& position,
344 const ComponentLayout* layout,
345 String& x, String& y, String& w, String& h)
347 // these are the code sections for the positions of the relative comps
348 String xrx, xry, xrw, xrh;
349 Component* const relCompX = layout != 0 ? layout->findComponentWithId (position.relativeToX) : 0;
350 if (relCompX != 0)
351 positionToCode (ComponentTypeHandler::getComponentPosition (relCompX), layout, xrx, xry, xrw, xrh);
353 String yrx, yry, yrw, yrh;
354 Component* const relCompY = layout != 0 ? layout->findComponentWithId (position.relativeToY) : 0;
355 if (relCompY != 0)
356 positionToCode (ComponentTypeHandler::getComponentPosition (relCompY), layout, yrx, yry, yrw, yrh);
358 String wrx, wry, wrw, wrh;
359 Component* const relCompW = (layout != 0 && position.rect.getWidthMode() != PositionedRectangle::absoluteSize)
360 ? layout->findComponentWithId (position.relativeToW) : 0;
361 if (relCompW != 0)
362 positionToCode (ComponentTypeHandler::getComponentPosition (relCompW), layout, wrx, wry, wrw, wrh);
364 String hrx, hry, hrw, hrh;
365 Component* const relCompH = (layout != 0 && position.rect.getHeightMode() != PositionedRectangle::absoluteSize)
366 ? layout->findComponentWithId (position.relativeToH) : 0;
367 if (relCompH != 0)
368 positionToCode (ComponentTypeHandler::getComponentPosition (relCompH), layout, hrx, hry, hrw, hrh);
370 // width
371 if (position.rect.getWidthMode() == PositionedRectangle::proportionalSize)
373 if (wrw.isNotEmpty())
374 w << "roundFloatToInt ((" << wrw << ") * " << valueToFloat (position.rect.getWidth()) << ")";
375 else
376 w << "proportionOfWidth (" << valueToFloat (position.rect.getWidth()) << ")";
378 else if (position.rect.getWidthMode() == PositionedRectangle::parentSizeMinusAbsolute)
380 if (wrw.isNotEmpty())
381 w << "(" << wrw << ") - " << roundToInt (position.rect.getWidth());
382 else
383 w << "getWidth() - " << roundToInt (position.rect.getWidth());
385 else
387 if (wrw.isNotEmpty())
388 w << "(" << wrw << ") + ";
390 w << roundToInt (position.rect.getWidth());
393 // height
394 if (position.rect.getHeightMode() == PositionedRectangle::proportionalSize)
396 if (hrh.isNotEmpty())
397 h << "roundFloatToInt ((" << hrh << ") * " << valueToFloat (position.rect.getHeight()) << ")";
398 else
399 h << "proportionOfHeight (" << valueToFloat (position.rect.getHeight()) << ")";
401 else if (position.rect.getHeightMode() == PositionedRectangle::parentSizeMinusAbsolute)
403 if (hrh.isNotEmpty())
404 h << "(" << hrh << ") - " << roundToInt (position.rect.getHeight());
405 else
406 h << "getHeight() - " << roundToInt (position.rect.getHeight());
408 else
410 if (hrh.isNotEmpty())
411 h << "(" << hrh << ") + ";
413 h << roundToInt (position.rect.getHeight());
416 // x-pos
417 if (position.rect.getPositionModeX() == PositionedRectangle::proportionOfParentSize)
419 if (xrx.isNotEmpty() && xrw.isNotEmpty())
420 x << "(" << xrx << ") + roundFloatToInt ((" << xrw << ") * " << valueToFloat (position.rect.getX()) << ")";
421 else
422 x << "proportionOfWidth (" << valueToFloat (position.rect.getX()) << ")";
424 else if (position.rect.getPositionModeX() == PositionedRectangle::absoluteFromParentTopLeft)
426 if (xrx.isNotEmpty())
427 x << "(" << xrx << ") + ";
429 x << roundToInt (position.rect.getX());
431 else if (position.rect.getPositionModeX() == PositionedRectangle::absoluteFromParentBottomRight)
433 if (xrx.isNotEmpty())
434 x << "(" << xrx << ") + (" << xrw << ")";
435 else
436 x << "getWidth()";
438 const int d = roundToInt (position.rect.getX());
439 if (d != 0)
440 x << " - " << d;
442 else if (position.rect.getPositionModeX() == PositionedRectangle::absoluteFromParentCentre)
444 if (xrx.isNotEmpty())
445 x << "(" << xrx << ") + (" << xrw << ") / 2";
446 else
447 x << "(getWidth() / 2)";
449 const int d = roundToInt (position.rect.getX());
450 if (d != 0)
451 x << " + " << d;
454 if (w != "0")
456 if (position.rect.getAnchorPointX() == PositionedRectangle::anchorAtRightOrBottom)
457 x << " - " << w;
458 else if (position.rect.getAnchorPointX() == PositionedRectangle::anchorAtCentre)
459 x << " - ((" << w << ") / 2)";
462 // y-pos
463 if (position.rect.getPositionModeY() == PositionedRectangle::proportionOfParentSize)
465 if (yry.isNotEmpty() && yrh.isNotEmpty())
466 y << "(" << yry << ") + roundFloatToInt ((" << yrh << ") * " << valueToFloat (position.rect.getY()) << ")";
467 else
468 y << "proportionOfHeight (" << valueToFloat (position.rect.getY()) << ")";
470 else if (position.rect.getPositionModeY() == PositionedRectangle::absoluteFromParentTopLeft)
472 if (yry.isNotEmpty())
473 y << "(" << yry << ") + ";
475 y << roundToInt (position.rect.getY());
477 else if (position.rect.getPositionModeY() == PositionedRectangle::absoluteFromParentBottomRight)
479 if (yry.isNotEmpty())
480 y << "(" << yry << ") + (" << yrh << ")";
481 else
482 y << "getHeight()";
484 const int d = roundToInt (position.rect.getY());
485 if (d != 0)
486 y << " - " << d;
488 else if (position.rect.getPositionModeY() == PositionedRectangle::absoluteFromParentCentre)
490 if (yry.isNotEmpty())
491 y << "(" << yry << ") + (" << yrh << ") / 2";
492 else
493 y << "(getHeight() / 2)";
495 const int d = roundToInt (position.rect.getY());
496 if (d != 0)
497 y << " + " << d;
500 if (h != "0")
502 if (position.rect.getAnchorPointY() == PositionedRectangle::anchorAtRightOrBottom)
503 y << " - " << h;
504 else if (position.rect.getAnchorPointY() == PositionedRectangle::anchorAtCentre)
505 y << " - ((" << h << ") / 2)";
509 const String justificationToCode (const Justification& justification)
511 switch (justification.getFlags())
513 case Justification::centred:
514 return "Justification::centred";
516 case Justification::centredLeft:
517 return "Justification::centredLeft";
519 case Justification::centredRight:
520 return "Justification::centredRight";
522 case Justification::centredTop:
523 return "Justification::centredTop";
525 case Justification::centredBottom:
526 return "Justification::centredBottom";
528 case Justification::topLeft:
529 return "Justification::topLeft";
531 case Justification::topRight:
532 return "Justification::topRight";
534 case Justification::bottomLeft:
535 return "Justification::bottomLeft";
537 case Justification::bottomRight:
538 return "Justification::bottomRight";
540 case Justification::left:
541 return "Justification::left";
543 case Justification::right:
544 return "Justification::right";
546 case Justification::horizontallyCentred:
547 return "Justification::horizontallyCentred";
549 case Justification::top:
550 return "Justification::top";
552 case Justification::bottom:
553 return "Justification::bottom";
555 case Justification::verticallyCentred:
556 return "Justification::verticallyCentred";
558 case Justification::horizontallyJustified:
559 return "Justification::horizontallyJustified";
561 default:
562 jassertfalse
563 break;
566 return "Justification (" + String (justification.getFlags()) + ")";
569 //==============================================================================
570 void drawResizableBorder (Graphics& g,
571 int w, int h,
572 const BorderSize<int> borderSize,
573 const bool isMouseOver)
575 g.setColour (Colours::orange.withAlpha (isMouseOver ? 0.4f : 0.3f));
577 g.fillRect (0, 0, w, borderSize.getTop());
578 g.fillRect (0, 0, borderSize.getLeft(), h);
579 g.fillRect (0, h - borderSize.getBottom(), w, borderSize.getBottom());
580 g.fillRect (w - borderSize.getRight(), 0, borderSize.getRight(), h);
582 g.drawRect (borderSize.getLeft() - 1, borderSize.getTop() - 1,
583 w - borderSize.getRight() - borderSize.getLeft() + 2,
584 h - borderSize.getTop() - borderSize.getBottom() + 2);
587 void drawMouseOverCorners (Graphics& g, int w, int h)
589 RectangleList r (Rectangle<int> (0, 0, w, h));
590 r.subtract (Rectangle<int> (1, 1, w - 2, h - 2));
592 const int size = jmin (w / 3, h / 3, 12);
593 r.subtract (Rectangle<int> (size, 0, w - size - size, h));
594 r.subtract (Rectangle<int> (0, size, w, h - size - size));
596 g.setColour (Colours::darkgrey);
598 for (int i = r.getNumRectangles(); --i >= 0;)
599 g.fillRect (r.getRectangle (i));
604 //==============================================================================
605 RelativePositionedRectangle::RelativePositionedRectangle()
606 : relativeToX (0),
607 relativeToY (0),
608 relativeToW (0),
609 relativeToH (0)
613 RelativePositionedRectangle::RelativePositionedRectangle (const RelativePositionedRectangle& other)
614 : rect (other.rect),
615 relativeToX (other.relativeToX),
616 relativeToY (other.relativeToY),
617 relativeToW (other.relativeToW),
618 relativeToH (other.relativeToH)
622 RelativePositionedRectangle& RelativePositionedRectangle::operator= (const RelativePositionedRectangle& other)
624 rect = other.rect;
625 relativeToX = other.relativeToX;
626 relativeToY = other.relativeToY;
627 relativeToW = other.relativeToW;
628 relativeToH = other.relativeToH;
629 return *this;
632 RelativePositionedRectangle::~RelativePositionedRectangle()
636 //==============================================================================
637 bool RelativePositionedRectangle::operator== (const RelativePositionedRectangle& other) const throw()
639 return rect == other.rect
640 && relativeToX == other.relativeToX
641 && relativeToY == other.relativeToY
642 && relativeToW == other.relativeToW
643 && relativeToH == other.relativeToH;
646 bool RelativePositionedRectangle::operator!= (const RelativePositionedRectangle& other) const throw()
648 return ! operator== (other);
651 void RelativePositionedRectangle::getRelativeTargetBounds (const Rectangle<int>& parentArea,
652 const ComponentLayout* layout,
653 int& x, int& xw, int& y, int& yh,
654 int& w, int& h) const
656 Component* rx = 0;
657 Component* ry = 0;
658 Component* rw = 0;
659 Component* rh = 0;
661 if (layout != 0)
663 rx = layout->findComponentWithId (relativeToX);
664 ry = layout->findComponentWithId (relativeToY);
665 rw = layout->findComponentWithId (relativeToW);
666 rh = layout->findComponentWithId (relativeToH);
669 x = parentArea.getX() + (rx != 0 ? rx->getX() : 0);
670 y = parentArea.getY() + (ry != 0 ? ry->getY() : 0);
671 w = rw != 0 ? rw->getWidth() : parentArea.getWidth();
672 h = rh != 0 ? rh->getHeight() : parentArea.getHeight();
673 xw = rx != 0 ? rx->getWidth() : parentArea.getWidth();
674 yh = ry != 0 ? ry->getHeight() : parentArea.getHeight();
677 const Rectangle<int> RelativePositionedRectangle::getRectangle (const Rectangle<int>& parentArea,
678 const ComponentLayout* layout) const
680 int x, xw, y, yh, w, h;
681 getRelativeTargetBounds (parentArea, layout, x, xw, y, yh, w, h);
683 const Rectangle<int> xyRect ((xw <= 0 || yh <= 0) ? Rectangle<int>()
684 : rect.getRectangle (Rectangle<int> (x, y, xw, yh)));
686 const Rectangle<int> whRect ((w <= 0 || h <= 0) ? Rectangle<int>()
687 : rect.getRectangle (Rectangle<int> (x, y, w, h)));
689 return Rectangle<int> (xyRect.getX(), xyRect.getY(),
690 whRect.getWidth(), whRect.getHeight());
693 void RelativePositionedRectangle::getRectangleDouble (double& x, double& y, double& w, double& h,
694 const Rectangle<int>& parentArea,
695 const ComponentLayout* layout) const
697 int rx, rxw, ry, ryh, rw, rh;
698 getRelativeTargetBounds (parentArea, layout, rx, rxw, ry, ryh, rw, rh);
700 double dummy1, dummy2;
701 rect.getRectangleDouble (Rectangle<int> (rx, ry, rxw, ryh), x, y, dummy1, dummy2);
702 rect.getRectangleDouble (Rectangle<int> (rx, ry, rw, rh), dummy1, dummy2, w, h);
705 void RelativePositionedRectangle::updateFromComponent (const Component& comp,
706 const ComponentLayout* layout)
708 int x, xw, y, yh, w, h;
709 getRelativeTargetBounds (Rectangle<int> (0, 0, comp.getParentWidth(), comp.getParentHeight()),
710 layout, x, xw, y, yh, w, h);
712 PositionedRectangle xyRect (rect), whRect (rect);
713 xyRect.updateFrom (comp.getBounds(), Rectangle<int> (x, y, xw, yh));
714 whRect.updateFrom (comp.getBounds(), Rectangle<int> (x, y, w, h));
716 rect.setX (xyRect.getX());
717 rect.setY (xyRect.getY());
718 rect.setWidth (whRect.getWidth());
719 rect.setHeight (whRect.getHeight());
722 void RelativePositionedRectangle::updateFrom (double newX, double newY, double newW, double newH,
723 const Rectangle<int>& parentArea, const ComponentLayout* layout)
725 int x, xw, y, yh, w, h;
726 getRelativeTargetBounds (parentArea, layout, x, xw, y, yh, w, h);
728 PositionedRectangle xyRect (rect), whRect (rect);
729 xyRect.updateFromDouble (newX, newY, newW, newH, Rectangle<int> (x, y, xw, yh));
730 whRect.updateFromDouble (newX, newY, newW, newH, Rectangle<int> (x, y, w, h));
732 rect.setX (xyRect.getX());
733 rect.setY (xyRect.getY());
734 rect.setWidth (whRect.getWidth());
735 rect.setHeight (whRect.getHeight());
738 void RelativePositionedRectangle::applyToXml (XmlElement& e) const
740 e.setAttribute ("pos", rect.toString());
742 if (relativeToX != 0)
743 e.setAttribute ("posRelativeX", String::toHexString (relativeToX));
744 if (relativeToY != 0)
745 e.setAttribute ("posRelativeY", String::toHexString (relativeToY));
746 if (relativeToW != 0)
747 e.setAttribute ("posRelativeW", String::toHexString (relativeToW));
748 if (relativeToH != 0)
749 e.setAttribute ("posRelativeH", String::toHexString (relativeToH));
752 void RelativePositionedRectangle::restoreFromXml (const XmlElement& e,
753 const RelativePositionedRectangle& defaultPos)
755 rect = PositionedRectangle (e.getStringAttribute ("pos", defaultPos.rect.toString()));
756 relativeToX = e.getStringAttribute ("posRelativeX", String::toHexString (defaultPos.relativeToX)).getHexValue64();
757 relativeToY = e.getStringAttribute ("posRelativeY", String::toHexString (defaultPos.relativeToY)).getHexValue64();
758 relativeToW = e.getStringAttribute ("posRelativeW", String::toHexString (defaultPos.relativeToW)).getHexValue64();
759 relativeToH = e.getStringAttribute ("posRelativeH", String::toHexString (defaultPos.relativeToH)).getHexValue64();